#include <stdio.h>
#include <libavutil/log.h>
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>

int main(int argc, char const *argv[])
{
    av_log_set_level(AV_LOG_DEBUG);
    /**
     * 抽取音频数据的步骤
     * 1、处理一些参数
     * 2、打开源文件
     * 3、从源文件中找到音频流
     * 4、打开目标文件的上下文
     * 5、为目标文件，创建一个新的音频流
     * 6、设置目标文件音频流的参数
     * 7、写多媒体文件头到目标文件中
     * 8、从源文件中读取到音频数据写入到目标文件中
     * 9、写多媒体文件尾到目标文件中
     * 10、将申请的资源释放掉
     */

    // 定义的常量
    int ret = -1;
    int idx = -1;

    AVFormatContext *inFmtCtx = NULL;
    AVFormatContext *outFmtCtx = NULL;

    const AVOutputFormat *outFmt = NULL;
    AVStream *outStream = NULL;
    AVStream *inStream = NULL;

    AVPacket pkt;

    // 1、处理一些参数
    const char* src;
    const char* dst;

    if (argc < 3) {
        av_log(NULL,AV_LOG_INFO,"arguments must be more than 3\n");
        exit(-1);
    }

    src = argv[1];
    dst = argv[2];

    // 2、打开源文件
    if ((ret = avformat_open_input(&inFmtCtx,src,NULL,NULL)) < 0) {
        av_log(NULL,AV_LOG_ERROR,"%s\n",av_err2str(ret));
        exit(-1);
    }

    // 3、从源文件中找到音频流
    idx = av_find_best_stream(inFmtCtx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
    if (idx < 0) {
        av_log(inFmtCtx,AV_LOG_ERROR,"Does not include audio\n");
        goto _ERROR;
    }

    // 4、打开目标文件的上下文
    outFmtCtx = avformat_alloc_context();
    if (!outFmtCtx) {
         av_log(NULL,AV_LOG_ERROR,"NO Memory!\n");
         goto _ERROR;
    }
    outFmt = av_guess_format(NULL,dst,NULL);
    outFmtCtx->oformat = (AVOutputFormat *)outFmt;

    // 5、为目标文件，创建一个新的音频流
    outStream = avformat_new_stream(outFmtCtx,NULL);

    // 6、设置目标文件音频流的参数
    inStream = inFmtCtx->streams[idx];
    avcodec_parameters_copy(outStream->codecpar,inStream->codecpar);
    outStream->codecpar->codec_tag = 0;

    // 绑定，把输出上下文和目标文件进行绑定
    ret = avio_open2(&outFmtCtx->pb,dst,AVIO_FLAG_WRITE,NULL,NULL);
    if (ret < 0) {
        av_log(outFmtCtx,AV_LOG_ERROR,"%s",av_err2str(ret));
        goto _ERROR;
    }

    // 7、写多媒体文件头到目标文件中
    ret = avformat_write_header(outFmtCtx,NULL);
    if (ret < 0) {
        av_log(outFmtCtx,AV_LOG_ERROR,"%s",av_err2str(ret));
        goto _ERROR;
    }

    // 8、从源文件中读取到音频数据写入到目标文件中
    while(av_read_frame(inFmtCtx,&pkt) >=0 ) {
        if (pkt.stream_index == idx) {
            pkt.pts = av_rescale_q_rnd(pkt.pts,inStream->time_base,outStream->time_base,(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
            pkt.dts = av_rescale_q_rnd(pkt.dts,inStream->time_base,outStream->time_base,(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
            pkt.duration = av_rescale_q(pkt.duration,inStream->time_base,outStream->time_base);
            pkt.stream_index = 0;
            pkt.pos = -1;
            // 把源文件读出来的packet，写入到目标文件中
            av_interleaved_write_frame(outFmtCtx,&pkt);
            av_packet_unref(&pkt);
        }
    } 

    // 9、写多媒体文件尾到目标文件中
    av_write_trailer(outFmtCtx);
    
    // 10、将申请的资源释放掉
_ERROR:
    if (inFmtCtx) {
        avformat_close_input(&inFmtCtx);
        inFmtCtx = NULL;
    }
    if (outFmtCtx->pb) {
        avformat_free_context(outFmtCtx);
        outFmtCtx = NULL;
    }
    if (outFmtCtx) {
        avformat_free_context(outFmtCtx);
        outFmtCtx = NULL;
    }
    printf("hello world\n");
    return 0;
}
